﻿////TODO: Convolution3x3: This filter has to be tested

//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Drawing;
//using System.Drawing.Imaging;

//namespace LowLevelGraphics.Filter
//{
//    /// <summary>
//    /// Classical 3x3 convolution filter. 
//    /// </summary>
//    public class Convolution3x3 : BaseImageFilter
//    {
//        protected CConvMatrix m_ConvolutionMatrix = null;

//        /// <summary>
//        /// default constructor
//        /// </summary>
//        public Convolution3x3()
//            : this(new CConvMatrix())
//        {
//        }

//        /// <summary>
//        /// Initializes a new instance of the <see cref="Convolution3x3"/> class.
//        /// </summary>
//        /// <param name="_matrix">The _matrix.</param>
//        public Convolution3x3(CConvMatrix _matrix)
//        {
//            m_ConvolutionMatrix = _matrix;
//        }

//        /// <summary>
//        /// used by clone to create a deep copy
//        /// </summary>
//        /// <param name="_convolution3x3"></param>
//        internal Convolution3x3(Convolution3x3 _convolution3x3)
//        {
//            this.m_ConvolutionMatrix = _convolution3x3.m_ConvolutionMatrix;
//        }

//        /// <summary>
//        /// Gets or sets the matrix.
//        /// </summary>
//        /// <value>The matrix.</value>
//        public CConvMatrix Matrix
//        {
//            get { return m_ConvolutionMatrix; }
//            set { m_ConvolutionMatrix = value; }
//        }

//        /// <summary>
//        /// Execute this Filter
//        /// A Debug Statement is written if a concrete Filter is called
//        /// </summary>
//        /// <param name="_bitmap"></param>
//        /// <returns></returns>
//        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
//        {
//            UnsafeBitmap bitmap = _bitmap;
//            // Avoid divide by zero errors
//            if (0 == m_ConvolutionMatrix.Factor) return _bitmap;

//            UnsafeBitmap bSrc = (UnsafeBitmap)bitmap.Clone();

//            // GDI+ still lies to us - the return format is BGR, NOT RGB.
//            BitmapData bmData = bitmap.BitmapData;   //b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
//            BitmapData bmSrc = bSrc.BitmapData; // bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

//            int stride = bmData.Stride;
//            int stride2 = stride * 2;
//            IntPtr Scan0 = bmData.Scan0;
//            IntPtr SrcScan0 = bmSrc.Scan0;

//            unsafe
//            {
//                byte* p = (byte*)(void*)Scan0;
//                byte* pSrc = (byte*)(void*)SrcScan0;

//                int nOffset = stride - bitmap.Width * 4;
//                int nWidth = bitmap.Width - 2;
//                int nHeight = bitmap.Height - 2;

//                int nPixel;

//                for (int y = 0; y < nHeight; ++y)
//                {
//                    for (int x = 0; x < nWidth; ++x)
//                    {
//                        nPixel = ((((pSrc[2] * m_ConvolutionMatrix.TopLeft) + (pSrc[5] * m_ConvolutionMatrix.TopMid) + (pSrc[8] * m_ConvolutionMatrix.TopRight) +
//                            (pSrc[2 + stride] * m_ConvolutionMatrix.MidLeft) + (pSrc[5 + stride] * m_ConvolutionMatrix.Pixel) + (pSrc[8 + stride] * m_ConvolutionMatrix.MidRight) +
//                            (pSrc[2 + stride2] * m_ConvolutionMatrix.BottomLeft) + (pSrc[5 + stride2] * m_ConvolutionMatrix.BottomMid) + (pSrc[8 + stride2] * m_ConvolutionMatrix.BottomRight)) / m_ConvolutionMatrix.Factor) + m_ConvolutionMatrix.Offset);

//                        if (nPixel < 0) nPixel = 0;
//                        if (nPixel > 255) nPixel = 255;

//                        p[5 + stride] = (byte)nPixel;

//                        nPixel = ((((pSrc[1] * m_ConvolutionMatrix.TopLeft) + (pSrc[4] * m_ConvolutionMatrix.TopMid) + (pSrc[7] * m_ConvolutionMatrix.TopRight) +
//                            (pSrc[1 + stride] * m_ConvolutionMatrix.MidLeft) + (pSrc[4 + stride] * m_ConvolutionMatrix.Pixel) + (pSrc[7 + stride] * m_ConvolutionMatrix.MidRight) +
//                            (pSrc[1 + stride2] * m_ConvolutionMatrix.BottomLeft) + (pSrc[4 + stride2] * m_ConvolutionMatrix.BottomMid) + (pSrc[7 + stride2] * m_ConvolutionMatrix.BottomRight)) / m_ConvolutionMatrix.Factor) + m_ConvolutionMatrix.Offset);

//                        if (nPixel < 0) nPixel = 0;
//                        if (nPixel > 255) nPixel = 255;

//                        p[4 + stride] = (byte)nPixel;

//                        nPixel = ((((pSrc[0] * m_ConvolutionMatrix.TopLeft) + (pSrc[3] * m_ConvolutionMatrix.TopMid) + (pSrc[6] * m_ConvolutionMatrix.TopRight) +
//                            (pSrc[0 + stride] * m_ConvolutionMatrix.MidLeft) + (pSrc[3 + stride] * m_ConvolutionMatrix.Pixel) + (pSrc[6 + stride] * m_ConvolutionMatrix.MidRight) +
//                            (pSrc[0 + stride2] * m_ConvolutionMatrix.BottomLeft) + (pSrc[3 + stride2] * m_ConvolutionMatrix.BottomMid) + (pSrc[6 + stride2] * m_ConvolutionMatrix.BottomRight)) / m_ConvolutionMatrix.Factor) + m_ConvolutionMatrix.Offset);

//                        if (nPixel < 0) nPixel = 0;
//                        if (nPixel > 255) nPixel = 255;

//                        p[3 + stride] = (byte)nPixel;

//                        p += 4;
//                        pSrc += 4;
//                    }
//                    p += nOffset;
//                    pSrc += nOffset;
//                }
//            }

//            bSrc.Dispose();
//            return _bitmap;
//        }

//        /// <summary>
//        /// create a deep copy
//        /// </summary>
//        /// <returns></returns>
//        public override object Clone()
//        {
//            return new Convolution3x3(this);
//        }
//    }
//}
